package com.thitech.sif.interceptor;

import java.util.List;

import com.thitech.sif.AbsOutput;
import com.thitech.sif.Executor;
import com.thitech.sif.context.AbsContext;
import com.thitech.sif.exception.SifException;
import com.thitech.sif.utils.log.LogBuilder;
import com.thitech.sif.utils.log.LogFactory;
import com.thitech.sif.utils.log.SifLogger;

/**
 * 拦截器执行时使用工具类
 * @author shisheng.lian
 * @date 2014-04-09
 *
 */
public class InterceptorExecutor {
	
	private static final SifLogger log = LogFactory.getLogger(InterceptorExecutor.class);

	/**
	 * 服务调用前执行拦截器中方法
	 * @param interceptors
	 *             被执行拦截器
	 * @param serviceDataHolder
	 * 			   服务调用时需要的数据集合
	 * @return 返回true，则继续执行下一个拦截器，返回false则直接返回停止执行后面的拦截器链
	 * @throws Exception
	 * 			    出现异常直接抛出
	 */
	public static boolean invokeBefore(Executor executor)
			throws Exception{
		return executeInitAndBefore(executor);
	}
	
	/**
	 * 调用服务后执行拦截器中方法
	 * @param interceptors
	 *             被执行拦截器
	 * @param serviceDataHolder
	 * 			   服务调用时需要的数据集合
	 * @param output
	 * 			 服务返回数据对象
	 * @param e
	 * 			 服务框架执行期间出现的异常对象
	 * @throws Exception
	 * 			    出现异常直接抛出
	 */
	public static void invokeAfter(Executor executor,
			AbsOutput output, Throwable e) throws Exception{
		executeAfterAndDestroy(executor, output, e);
	}
	
	/**
	 * 拦截服务执行过程中最终出现的异常信息，并把异常转换成CPSServiceReturnCode对象，以及把异常记录到Defaulttrace中，方便查找原因
	 * @param interceptors
	 *             被执行拦截器
	 * @param serviceDataHolder
	 * 			   服务调用时需要的数据集合
	 * @param output
	 * 			 服务返回数据对象
	 * @param e
	 * 			 服务框架执行期间出现的异常对象
	 */
	public static void invokeLastFailInterceptor(InterceptorHandler failInterceptor, Executor executor,
			AbsOutput output, Throwable e){
		try{
			executeAfter(failInterceptor, executor,output, e);
		} catch(Exception laste){
			log.error("服务执行过程中，最终处理异常时出现异常", laste);
		}
	}
	
	/**
	 * 执行拦截器init及before方法
	 * @param interceptors
	 *             被执行拦截器
	 * @param serviceDataHolder
	 * 			   服务调用时需要的数据集合
	 * @return 返回true，则继续执行下一个拦截器，返回false则直接返回停止执行后面的拦截器链
	 * @throws Exception
	 * 			    出现异常直接抛出
	 */
	public static boolean executeInitAndBefore(Executor executor)
			throws Exception{
		boolean flag = true;
		AbsContext ctx = executor.getContext();
		if (null != ctx) {
			List<InterceptorHandler> interceptors = ctx.getInterceptors();
			if(null != interceptors && !interceptors.isEmpty()){
				for(int i=0; i<interceptors.size(); i++){
					InterceptorHandler interceptorHandler = interceptors.get(i);
					executeInit(interceptorHandler); // 执行初始化方法
					flag = executeBefore(interceptorHandler, executor); // 执行before方法
					if(!flag){ // 如果拦截器中有方法返回false，则直接退出拦截器链的执行
						break;
					}
				}
			}
		} else {
			throw new SifException("Application Context is null!");
		}
		return flag;
	}
	
	/**
	 * 执行拦截器Destroy及after方法
	 * @param interceptors
	 *             被执行拦截器
	 * @param serviceDataHolder
	 * 			   服务调用时需要的数据集合
	 * @param output
	 * 			 服务返回数据对象
	 * @param e
	 * 			 服务框架执行期间出现的异常对象
	 * @throws Exception
	 * 			    出现异常直接抛出
	 */
	public static void executeAfterAndDestroy(Executor executor, 
			AbsOutput output, Throwable e) throws Exception{
		AbsContext ctx = executor.getContext();
		if (null != ctx) {
			List<InterceptorHandler> interceptors = ctx.getInterceptors();
			if(null != interceptors && !interceptors.isEmpty()){
				for(int i = (interceptors.size() - 1); i>=0; i--){
					InterceptorHandler interceptorHandler = interceptors.get(i);
					executeAfter(interceptorHandler, executor, output, e); // 执行拦截器after方法
					log.debug(LogBuilder.interceptorAfterDebug(interceptorHandler, executor, output));
					executeDestroy(interceptorHandler); // 执行拦截器销毁方法
				}
			}
		} else {
			throw new SifException("Application Context is null!");
		}
	}
	
	/**
	 * 执行拦截器初始化方法
	 */
	private static void executeInit(InterceptorHandler interceptor){
		interceptor.init();
	}
	
	/**
	 * 执行拦截器销毁方法
	 */
	private static void executeDestroy(InterceptorHandler interceptor){
		interceptor.destroy();
	}
	
	/**
	 * 执行拦截器before方法
	 */
	private static boolean executeBefore(InterceptorHandler interceptor, Executor executor) throws Exception{
		log.debug(LogBuilder.interceptorBeforeDebug(interceptor, executor));
		return interceptor.beforeInvoke(executor);
	}
	
	/**
	 * 执行拦截器after方法
	 */
	private static void executeAfter(InterceptorHandler interceptor, Executor executor,
			AbsOutput output, Throwable e) throws Exception{
		interceptor.afterInvoke(executor, output, e);
	}
}
